package cn.monkey.config;

import cn.monkey.filter.JwtSecurityFilter;
import cn.monkey.mapper.MenuMapper;
import cn.monkey.mapper.RoleMapper;
import cn.monkey.pojo.Menu;
import cn.monkey.pojo.Role;
import cn.monkey.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

@Configuration
public class WebSecurityConfig {
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer(){
        return (web -> web.ignoring().requestMatchers("/images/**"));
    }

    @Autowired
    MenuMapper menuMapper;
    @Autowired
    RoleMapper roleMapper;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable();
        JwtSecurityFilter jwtSecurityFilter=new JwtSecurityFilter();
        http.addFilterBefore(jwtSecurityFilter, UsernamePasswordAuthenticationFilter.class);
        http.authorizeHttpRequests(ahr->
                ahr.requestMatchers("/login","/error").permitAll()
                        .anyRequest().access((authentication,object)->{
                            String uri = object.getRequest().getRequestURI();
                            List<Menu> menus = menuMapper.selectList(null);
                            boolean quanxian=false;
                            for (Menu menu : menus) {
                                if(uri.startsWith(menu.getUrl())){
                                    quanxian=true;
                                    List<String> roleNames= roleMapper.getRoleBymid(menu.getMid());
                                    Collection<? extends GrantedAuthority> authorities = authentication.get().getAuthorities();
                                    for (GrantedAuthority authority : authorities) {
                                        if(roleNames.contains(authority.getAuthority())){
                                            return new AuthorizationDecision(true);
                                        }
                                    }
                                    break;
                                }
                            }
                            if(!quanxian && !(authentication instanceof AnonymousAuthenticationToken) ){
                                return new AuthorizationDecision(true);
                            }
                            System.out.println("无权访问");
                            return new AuthorizationDecision(false);
                        })
        );
        http.formLogin(log->
                log.loginProcessingUrl("/login")
                        .successHandler((request,response,authentication)->{
                            response.setContentType("application/json;charset=utf-8");
                            String token = JwtUtils.createToken(authentication);
                            response.getWriter().write(token);
                        })
                        .failureHandler((request,response,exception)->{
                            response.setContentType("application/json;charset=utf-8");
                            response.getWriter().write("登录失败:"+exception.getMessage());
                        })

        );
        return http.build();
    }
}
